home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / ddj0190.arc / RAHNER.EXE / EGA_DRV.ASM < prev    next >
Assembly Source File  |  1989-09-21  |  20KB  |  786 lines

  1.     .model    small, c
  2.     .286    ; This directive can be used to optimize procedure entry
  3.         ; but not much else.  I avoided all non-8088 commands
  4.     comment \
  5.             EGA Sprite Drivers for C
  6.         Copyright (c) February 1989, Ryu Consulting, Inc.
  7.             (916) 722 - 1939 anytime
  8.  
  9.             Written by Rahner James, CS
  10.  
  11.     This is a full functioning sprite driver for EGA graphics
  12.     adaptors.  The sprite are given to the routines as a linked list
  13.     of sprite structures.  All the function are re-entrant and can be
  14.     part of a multi-tasking system.  The sprite structures are intended
  15.     to reside in far memory.  The sprite can exist on any pixel boundary.
  16.     These were intended to be called from some C program, but probably
  17.     can be modified for some other language.  This must be assembled with 
  18.     Microsoft MASM version 5.0 or later since I make use of local
  19.     variables, forward/backward jumps and models.  Expect to get some
  20.     incorrect size warnings because MASM doesn't seem to recognize its own
  21.     "byte ptr" and "word ptr" operators when used with words and dwords.
  22.  
  23.     \
  24.  
  25. ; ****************************************************************************
  26.  
  27. ;    EQUATES
  28.  
  29. ; ****************************************************************************
  30.  
  31. EOI        equ    20h        ; End Of Interrupt signal
  32. EOI_PORT    equ    20h        ; Port to output the EOI
  33. CRT_MODE    equ    49h
  34. EGA_ADDRESS    equ    63h
  35.  
  36. EGA_PIXELS_WORD equ    16        ; Number of pixels per word
  37. EGA_PIXELS_BYTE equ    8        ; Number of pixels per byte
  38. NUMBER_OF_PLANES equ    4        ; Number of EGA color planes
  39.  
  40. EGA_RETRACE_STATUS    equ    3dah    ; EGA retrace status register
  41. RETRACE_BIT        equ    1 shl 3    ; Bit set to signal a vertical retrace
  42. SEQUENCE_REG        equ    3c4h    ; Sequencer register
  43. GRAPHICS_12        equ    3ceh    ; Graphics 1 & 2 register
  44. MAP_MASK_REG        equ    2    ; Map mask Indexed register
  45. DATA_ROTATE_REG    equ    3    ; Data Rotate Indexed register
  46. DATA_OR        equ    1 shl 4    ; Set to OR data on the EGA
  47. DATA_MOVE        equ    0    ; Write data unmodified onto EGA
  48.  
  49. BOTTOM_LINE        equ    200    ; Lowest pixel line to allow a sprite
  50. RIGHT_SIDE        equ    640    ; Right-most visual pixel allowed
  51.  
  52.  
  53. ; ****************************************************************************
  54.  
  55. ;    STRUCTURES
  56.  
  57. ; ****************************************************************************
  58.  
  59. ; All sprites are stored on disk using the same internal format.
  60. ; The first word is the width of the sprites in bytes and the second
  61. ; word is the height of the sprite in widths.  Each byte represents
  62. ; one pixel's worth of information.  Bit 7 of the byte is the intensity
  63. ; bit, 0=off.  This allows for 128 colors, black will be 0 or 80h.  The
  64. ; intensity bit set indicates an opaque black surface.  All color
  65. ; translations are table driven.
  66.  
  67. internal_sprite_structure    struc    ; Storage structure used for all sprites
  68. int_width    dw    ?        ; Width in bytes for the sprite
  69. int_height    dw    ?        ; Height in widths of the sprite
  70. int_body    db    ?        ; Start of the sprite's body
  71. internal_sprite_structure    ends
  72.  
  73.  
  74. ega_sprite_structure    struc    ; Internal EGA sprite structure
  75. e_animate_ptr    dw    0,0    ; Far ptr to next sprite struct in animation seq.
  76. e_width    dw    ?    ; Width of the sprite in words
  77. e_height    dw    ?    ; Height of sprite in widths
  78. e_body        dw    ?    ; Beginning of body
  79.                 ;.word 0: mask, word 1: sprite
  80.                 ;.throughout the body.  That way you can pull
  81.                 ;.the background up, mask it, OR the sprite,
  82.                 ;.then store the background
  83.                 ; The body is organized into four planes,
  84.                 ;.termed PLANE0 to PLANE3.  Each represents a
  85.                 ;.different color in the EGA spectrum, except
  86.                 ;.PLANE0 which is the intensity bit.
  87. ega_sprite_structure    ends
  88.  
  89.  
  90. style_structure    struc
  91. style_width    dw    ?        ; Width of each style entry in bytes
  92. style_height    dw    ?        ; Height of each style entry in pixels
  93. style_body    db    ?        ; Start of the style entries
  94. style_structure    ends
  95.  
  96.  
  97. ; ****************************************************************************
  98.  
  99. ;    LOCAL DATA STORAGE for DS
  100.  
  101. ; ****************************************************************************
  102.  
  103. .data
  104.  
  105. public        do_page_flip, done_page_flip
  106.     even
  107.  
  108. do_page_flip    db    0    ; Set to -1 when non-visual page is completed
  109. done_page_flip    db    -1    ; Set to -1 right after page has been swapped
  110. flip_turn    db    4    ; # of interrupts before an EGA page flip
  111.  
  112. old_irq_mask    db    0    ; Old IRQ mask
  113.  
  114. EGA_settings    db    2bh,2bh,2bh,2bh,24h,24h,23h,2eh
  115.         db    0,0,0,0,0,24h,23h,2eh,2bh
  116.  
  117.     even
  118. ega_base_port        dw    ?
  119. default_retrace    label    word
  120. v_retrace_reg        db    11h
  121. v_retrace_value    db    ?
  122.  
  123.  
  124. .code
  125. ; ****************************************************************************
  126.  
  127. ;    LOCAL DATA STORAGE for CS
  128.  
  129. ; ****************************************************************************
  130.  
  131.     even
  132.  
  133. ega_segment    dw    0a800h    ; EGA page memory segment being set up
  134. old_vector    dw    0,0    ; Old IRQ-2 vector (as Checkov would say wecter)
  135.  
  136.  
  137. ; EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  138.  
  139. ; EGA sprite related routines below this line
  140.  
  141. ; void    EGA_CONVERT( dest_ptr, source_ptr )
  142. ; Converts long storage format sprite into EGA structure sprite
  143. ; Given:
  144. ;    dest_ptr far -> EGA sprite buffer ready to go
  145. ;    source_ptr far -> disk sprite structure to convert
  146. ; Returns:
  147. ;    EGA sprite buffer set up accordingly
  148.  
  149. ega_convert proc near uses di si ds, dest:dword, source:dword
  150. local    store_width:word, store_height:word
  151. local    source_width:word
  152. local    plane_size:word
  153.  
  154.     cld
  155.     lds    si, source        ; DS:SI -> source sprite
  156.     les    di, dest        ; ES:DI -> CGA sprite buffer
  157.  
  158.     mov    es:[di], di        ; Make the animate ptr point to itself
  159.     mov    es:[di+2], es
  160.     add    di, E_WIDTH
  161.  
  162.     lodsw                ; Get width in byte pixels
  163.     mov    source_width, ax
  164.     add    ax, EGA_PIXELS_WORD-1    ; Want to include those border pixels
  165.     mov    cl, 4            ; Divide by sixteen to convert one byte
  166.     shr    ax, cl            ;.per pixel to 16 pixels per word for EGA
  167.     mov    bx, ax            ; Use this as our width count
  168.     stosw                ; Store as words/pixels
  169.     lodsw                ; Get height
  170.     mov    store_height, ax
  171.     stosw                ; Move height straight across
  172.     mul    bx            ; AX = Body size in mask/sprite entries
  173.     add    ax, ax            ; AX = body size in words
  174.     add    ax, ax            ; AX = plane size in bytes
  175.     mov    plane_size, ax        ; Save as our plane index
  176.  
  177.     mov    ax, ds            ; Swap DS:SI and ES:DI
  178.     mov    bx, es
  179.     mov    ds, bx
  180.     mov    es, ax
  181.     xchg    di, si
  182.  
  183.     sub    si, 4            ; This is to prep for the next INC
  184. next_row:
  185.     mov    cx, source_width    ; Get source row width
  186. next_word:
  187.     add    si, 4            ; SI -> next word in line
  188.     mov    dx, -1            ; DX = the destination mask
  189.     xor    ax, ax
  190.     mov    [si], dx        ; Set the mask word
  191.     mov    [si+2], ax        ; Clear the sprite word
  192.     mov    bx, plane_size        ; BX offset to next plane
  193.     mov    [si+bx], dx        ; Set the mask word
  194.     mov    [si+bx+2], ax        ; Clear the sprite word
  195.     add    bx, plane_size        ; BX offset to next plane
  196.     mov    [si+bx], dx        ; Set the mask word
  197.     mov    [si+bx+2], ax        ; Clear the sprite word
  198.     add    bx, plane_size        ; BX offset to next plane
  199.     mov    [si+bx], dx        ; Set the mask word
  200.     mov    [si+bx+2], ax        ; Clear the sprite word
  201.  
  202.     mov    dx, 1 shl 7        ; Start at MSB which is pixel LSB
  203. next_pixel_byte:
  204.     jc    next_word        ; Only be set by pixel shift below
  205.     mov    al, es:[di]        ; Get the source pixel byte
  206.     inc    di            ; DI -> next source pixel byte
  207.     or    al, al            ; See if it's anything at all
  208.     jz    end_pixel_byte        ; Skip all the checks
  209.  
  210.     xor    [si], dx        ; Reset the mask bit
  211.     test    al, 1 shl 4        ; Check bit 7
  212.     jz    @F            ; Skip if nothing here
  213.     or    [si+2], dx        ; Place the sprite bit
  214. @@:    mov    bx, plane_size        ; BX -> plane 1 offset
  215.     xor    [si+bx], dx        ; Clear the mask bit
  216.     test    al, 1 shl 7        ; Check bit 6
  217.     jz    @F            ; Skip if nothing here
  218.     or    [si+bx+2], dx        ; Place the sprite bit
  219. @@:    add    bx, plane_size        ; BX -> plane 2 offset
  220.     xor    [si+bx], dx        ; Clear the mask bit
  221.     test    al, 1 shl 6        ; Check bit 5
  222.     jz    @F            ; Skip if nothing here
  223.     or    [si+bx+2], dx        ; Place the sprite bit
  224. @@:    add    bx, plane_size        ; BX -> plane 3 offset
  225.     xor    [si+bx], dx        ; Clear the mask bit
  226.     test    al, 1 shl 5        ; Check bit 4
  227.     jz    end_pixel_byte        ; Skip if nothing here
  228.     or    [si+bx+2], dx        ; Place the sprite bit
  229.  
  230. end_pixel_byte:
  231.     shr    dl, 1            ; Move our pixel bit toward MS pixel bit
  232.     rcr    dh, 1
  233.     loop    next_pixel_byte        ; Loop through the pixel bytes
  234.  
  235.     dec    store_height        ; One less row
  236.     jnz    next_row
  237.  
  238.     ret
  239. ega_convert    endp
  240.  
  241.  
  242. ; EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  243. ;
  244. ; ui EGA_CALCULATE( source_ptr )
  245. ; Calculates the amount of storage needed for an unconverted sprite
  246. ; Given:
  247. ;    source_ptr far -> disk sprite structure to convert
  248. ; Returns:
  249. ;    AX = number of bytes needed to store the converted sprite
  250.  
  251. ega_calculate proc near uses si ds, source:dword
  252.     lds    si, source        ; DS:SI -> disk sprite structure for calculation
  253.     mov    ax, [si]        ; Get the width in bytes
  254.     add    ax, EGA_PIXELS_WORD-1    ; Round up to nearest word
  255.     shr    ax, 4            ; AX = number of words for stoarge
  256.     add    ax, ax            ; AX = number of bytes storage
  257.     add    ax, ax            ; AX = number of globs in one row
  258.     add    ax, ax            ; AX = number of row/planes
  259.     add    ax, ax
  260.     mul    word ptr [si].int_height ; AX = bytes per row * number of rows
  261.     add    ax, E_BODY        ; AX = body size + header size
  262.     ret
  263. ega_calculate    endp
  264.  
  265.  
  266. ; EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  267. ;
  268. ; void PUT_SPRITE( ui X, ui Y, ega_sprite_structure far *SPRITE_PTR )
  269. ; Maps a sprite list into the display video buffer
  270. ; Sprite is assumed to be 32-bits wide
  271. ; Given:
  272. ;    X = X pixel location of sprite
  273. ;    Y = Y pixel location of sprite
  274. ;    SPRITE_PTR -> sprite structure to put on the screen
  275. ; Returns:
  276. ;    The sprite is mapped onto the screen buffer
  277. put_sprite proc uses di si, x:word, y:word, sprite_ptr:dword
  278.  
  279. local    mask_msw:word            ; OR'ed with the mask dword
  280. local    mask_lsw:word
  281. local    or_msw:word            ; AND'ed with the sprite dword
  282. local    or_lsw:word
  283. local    start_di:word
  284. local    start_si:word
  285. local    sprite_plane_size:word
  286. local    number_of_rows:word
  287. local    shift:byte
  288. local    plane_number:byte
  289.  
  290.     push    ds
  291.     cmp    y, 200            ; See if below 200
  292.     jc    @F
  293. short_done:
  294.     jmp    done
  295. @@:    cmp    x, 640
  296.     jnc    short_done
  297.  
  298.     cld
  299.     mov    es, ega_segment
  300.     lds    si, sprite_ptr        ; DS:SI -> sprite to be driven
  301.  
  302.     mov    ax, 80            ; Calculate the offset
  303.     mul    y
  304.     mov    cx, x
  305.     mov    di, cx
  306.     and    cl, 7            ; CL = shift value
  307.     mov    shift, cl
  308.     shr    di, 3
  309.     add    di, ax            ; DI -> byte offset
  310.     mov    start_di, di
  311.  
  312.     mov    ax, [si].e_height    ; AX = height of the sprite in rows
  313.     mov    number_of_rows, ax    ; Save for later use
  314.     shl    ax, 3            ; AX *= 8, to get size of 1 sprite plane
  315.     mov    sprite_plane_size, ax
  316.  
  317.     mov    ax, number_of_rows    ; Let's see if it goes too low
  318.     add    ax, y
  319.     sub    ax, BOTTOM_LINE
  320.     jbe    @F            ; Skip if it doesn't
  321.     sub    number_of_rows, ax    ; Update the number of rows
  322.  
  323. @@:    add    si, E_BODY        ; SI -> start of sprite body
  324.     mov    start_si, si
  325.  
  326.     cmp    x, 640-32        ; See if we are going to be right
  327.     ja    short_mask        ; Skip if no mask
  328.     cmp    shift, 0
  329.     jnz    shifted
  330.  
  331.     mov    bl, NUMBER_OF_PLANES
  332. next_plane:
  333.     dec    bl
  334.  
  335.     mov    dx, GRAPHICS_12        ; Talk to EGA control logic
  336.     mov    al, 4
  337.     mov    ah, bl
  338.     out    dx, ax
  339.  
  340.     mov    dx, SEQUENCE_REG    ; Set up the ports for writing as well
  341.     mov    ax, 100h + MAP_MASK_REG
  342.     mov    cl, bl
  343.     shl    ah, cl
  344.     out    dx, ax
  345.  
  346.     mov    cx, number_of_rows
  347. @@:    mov    ax, es:[di]        ; Get the background dword
  348.     mov    dx, es:[di+2]
  349.     and    ax, [si]        ; Do the mask dword
  350.     and    dx, [si+4]
  351.     or    ax, [si+2]        ; Bring on the sprite
  352.     or    dx, [si+6]
  353.     mov    es:[di], ax        ; Replace with new graphic dword
  354.     mov    es:[di+2], dx
  355.     add    si, 8            ; Next row stuff
  356.     add    di, 80
  357.     loop    @B
  358.  
  359.     mov    di, start_di
  360.     mov    si, start_si
  361.     add    si, sprite_plane_size
  362.     mov    start_si, si
  363.     or    bl, bl
  364.     jnz    next_plane
  365.     jmp    done
  366. short_mask:
  367.     jmp    masked
  368.  
  369. shifted:
  370.     mov    plane_number, NUMBER_OF_PLANES-1
  371.     mov    cl, shift
  372.     mov    bh, -1
  373.     shr    bh, cl
  374. next_shift_plane:
  375.     mov    dx, GRAPHICS_12        ; Talk to EGA control logic
  376.     mov    al, 4
  377.     mov    ah, plane_number
  378.     out    dx, ax
  379.  
  380.     mov    dx, SEQUENCE_REG    ; Set up the ports for writing as well
  381.     mov    ax, 100h + MAP_MASK_REG
  382.     mov    cl, plane_number
  383.     shl    ah, cl
  384.     out    dx, ax
  385.  
  386.     mov    ch, byte ptr number_of_rows
  387.     mov    cl, shift
  388. @@:    lodsw                ; Get the sprite mask
  389.     xchg    ah, al            ; Switch them around
  390.     ror    ax, cl
  391.     mov    bl, ah            ; Top CL bits are ones to mask third byte
  392.     not    bh            ; BH = ~BH
  393.     and    bl, bh
  394.     or    ah, bh            ; Now set the top ones of source byte
  395.     mov    dx, es:[di]        ; Get the first destination word
  396.     xchg    ah, al            ; Re-order the mask bytes
  397.     and    dx, ax            ; Mask it
  398.     lodsw                ; Get the sprite
  399.     xchg    ah, al
  400.     ror    ax, cl
  401.     or    dh, al            ; OR DH w/ old AH
  402.     mov    al, ah            ; Save the upper bits
  403.     and    ah, bh            ; Mask off other bits
  404.     not    bh            ; BH = BH
  405.     and    al, bh            ; Cut out the rotunds
  406.     or    dl, al            ; OR least sig. bytes
  407.     mov    es:[di], dx        ; Save that first word, whew!
  408.  
  409.     mov    dl, ah            ; DL = pushed up sprite bits
  410.  
  411.     lodsw                ; Get the next sprite mask
  412.     xchg    ah, al            ; Switch them around
  413.     ror    ax, cl
  414.     mov    dh, ah            ; DH = MS shifted mask bits
  415.     and    ah, bh            ; Get rid of shifted bits
  416.     or    ah, bl            ; OR with shifted mask from previous byte
  417.     or    dh, bh            ; Add on the mask
  418.     xchg    ah, al            ; AH:AL back to normal
  419.     and    es:[di+4], dh        ; Easy way to get rid of DH
  420.     mov    bl, dl            ; BL = previous sprite bits
  421.     mov    dx, es:[di+2]        ; Get the destination word
  422.     and    dx, ax            ; Mask it
  423.     lodsw                ; Get the sprite
  424.     xchg    ah, al
  425.     ror    ax, cl
  426.     or    dh, al            ; OR DH w/ old AH
  427.     mov    al, ah            ; Save the upper bits
  428.     not    bh            ; BH = ~BH
  429.     and    ah, bh            ; Mask off other bits
  430.     not    bh            ; BH = BH
  431.     and    al, bh            ; Cut out the rotunds
  432.     or    al, bl
  433.     or    dl, al            ; OR least sig. bytes
  434.     mov    es:[di+2], dx        ; Save that first word, whew!
  435.     or    es:[di+4], ah
  436.  
  437.     add    di, 80
  438.  
  439.     dec    ch
  440.     jnz    @B
  441.  
  442.     mov    di, start_di
  443.     mov    si, start_si
  444.     add    si, sprite_plane_size
  445.     mov    start_si, si
  446.     sub    plane_number, 1
  447.     jc    @F
  448.     jmp    next_shift_plane
  449. @@:    jmp    done
  450.  
  451. masked:
  452.     xor    ax, ax            ; Set up masks and ORs
  453.     mov    mask_lsw, ax
  454.     mov    mask_msw, ax
  455.     dec    ax
  456.     mov    or_lsw, ax
  457.     mov    or_msw, ax
  458.  
  459.     cmp    x, 640-24        ; See if we have masked it already
  460.     jc    @F            ; Skip if we have
  461.     mov    mask_msw, 0ff00h
  462.     mov    or_msw, 0ffh
  463.  
  464.     cmp    x, 640-16
  465.     jc    @F
  466.     mov    mask_msw, -1        ; Make sure nothing gets masked
  467.     mov    or_msw, 0
  468.  
  469.     cmp    x, 640-8        ; See if that's all
  470.     jc    @F
  471.     mov    mask_lsw, 0ff00h
  472.     mov    or_lsw, 0ffh
  473.  
  474. @@:    mov    plane_number, NUMBER_OF_PLANES-1
  475. next_mask_plane:
  476.     mov    dx, GRAPHICS_12        ; Talk to EGA control logic
  477.     mov    al, 4
  478.     mov    ah, plane_number
  479.     out    dx, ax
  480.  
  481.     mov    dx, SEQUENCE_REG    ; Set up the ports for writing as well
  482.     mov    ax, 100h + MAP_MASK_REG
  483.     mov    cl, plane_number
  484.     shl    ah, cl
  485.     out    dx, ax
  486.  
  487.     mov    cx, number_of_rows
  488. @@:    mov    ax, [si]        ; Get the first mask
  489.     mov    dx, [si+4]        ; Get the second mask
  490.     or    ax, mask_lsw
  491.     or    dx, mask_msw
  492.     and    ax, es:[di]        ; Get the background dword
  493.     and    dx, es:[di+2]
  494.     mov    bx, or_lsw        ; Get the OR lsw
  495.     and    bx, [si+2]        ; Bring on the sprite
  496.     or    ax, bx
  497.     mov    bx, or_msw
  498.     and    bx, [si+6]
  499.     or    dx, bx
  500.     mov    es:[di], ax        ; Replace with new graphic dword
  501.     mov    es:[di+2], dx
  502.     add    si, 8            ; Next row stuff
  503.     add    di, 80
  504.     loop    @B
  505.  
  506.     mov    di, start_di
  507.     mov    si, start_si
  508.     add    si, sprite_plane_size
  509.     mov    start_si, si
  510.     sub    plane_number, 1
  511.     jnc    next_mask_plane
  512.     jmp    done
  513.  
  514. done:    pop    ds
  515.     ret
  516. put_sprite    endp
  517.  
  518.  
  519. ; EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  520. ;
  521. ; void EGA_CLEAR_AREA( ui X1, ui Y1, ui X2, ui Y2 )
  522. ; Clears an area on the EGA display to black
  523. ; Given:
  524. ;    X1,Y1 = X,Y pixel coordinates of the upper left corner
  525. ;    X2,Y2 = X,Y pixel coordinates of the lower right corner
  526. ; Returns:
  527. ;    Rectangular area from X1,Y1 to X2,Y2 (inclusive) cleared to black
  528.  
  529. public ega_clear_area
  530. ega_clear_area proc uses ds si di, x1:word, y1:word, x2:word, y2:word
  531. local    height:word
  532. local    di_start:word
  533. local    word_columns:word
  534. local    di_offset:word
  535.  
  536.     cld
  537.  
  538.     cmp    x1, 640            ; See if too far to the right
  539.     jc    @F
  540.     mov    x1, 0
  541. @@:    cmp    x2, 640
  542.     jc    @F
  543.     mov    x2, 639
  544.  
  545. @@:    mov    ax, y2            ; Check out number of rows
  546.     sub    ax, y1
  547.     jnc    @F            ; See if jerk put them in backwards
  548.     neg    ax
  549. @@:    inc    ax
  550.     mov    bx, ax            ; BX = number of rows
  551.     mov    height, ax
  552.  
  553.     mov    ax, y1            ; Check our starting offset
  554.     mov    cx, 80
  555.     mov    di_offset, cx
  556.     mul    cx
  557.     mov    di, ax
  558.     mov    ax, x1            ; See where we start
  559.     shr    ax, 3
  560.     add    di, ax
  561.  
  562.     mov    ax, x2
  563.     sub    ax, x1
  564.     jnc    @F
  565.     neg    ax
  566. @@:    add    ax, 16
  567.     shr    ax, 4
  568.     jnz    @F
  569.     jmp    done
  570.  
  571. @@:    mov    word_columns, ax
  572.     add    ax, ax
  573.     sub    di_offset, ax
  574.     mov    es, ega_segment
  575.  
  576.     mov    dx, SEQUENCE_REG    ; Set up the ports for writing
  577.     mov    ax, 0f00h+MAP_MASK_REG
  578.     out    dx, ax
  579.  
  580.     mov    dx, di_offset
  581.     xor    ax, ax
  582.     mov    di_start, di
  583. @@:    mov    cx, word_columns
  584.     rep    stosw
  585.     add    di, dx
  586.     dec    bx
  587.     jnz    @B
  588.  
  589. done:    ret
  590. ega_clear_area endp
  591.  
  592.  
  593. ; EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  594. ;
  595. ; void EGA_INSTALL()
  596. ; Installs IRQ-2 vectors for EGA card
  597. ; Given:
  598. ;    nothing
  599. ; Returns:
  600. ;    -1 if neither EGA or VGA else
  601. ;    EGA interrupt vector installed and enabled
  602. public    ega_install
  603.  
  604. ega_install proc
  605.     mov    ax, 40h            ; ES -> video BIOS data area
  606.     mov    es, ax
  607.  
  608.     mov    dx, es:[EGA_ADDRESS]    ; DX -> CRTC Address port
  609.     mov    ega_base_port, dx    ; Save the port address
  610.  
  611.     mov    ax, 1a00h        ; Read display combination
  612.     int    10h
  613.     cmp    al, 1ah            ; See if EGA
  614.     jne    ega_adaptor
  615.     cmp    bl, 7            ; See if VGA
  616.     je    vga_adaptor
  617.     cmp    bl, 8
  618.     je    vga_adaptor
  619. error_out:
  620.     mov    ax, -1
  621.     jmp    short done
  622.  
  623. ega_adaptor:
  624.     mov    al, es:[CRT_MODE]    ; AL = video BIOS mode number
  625.     mov    bx, offset EGA_settings
  626.     xlat
  627.     jmp    short @F
  628.  
  629. vga_adaptor:
  630.     mov    al, v_retrace_reg        ; AL = Vertical retrace register
  631.     out    dx, al
  632.     inc    dx
  633.     in    al, dx
  634.  
  635. @@:    mov    v_retrace_value, al
  636.  
  637.     mov    done_page_flip, -1
  638.     mov    do_page_flip, 0
  639.  
  640.     xor    ax, ax            ; ES -> base page
  641.     mov    es, ax
  642.     mov    bx, 0ah*4        ; Vector for IRQ 2
  643.     mov    dx, cs
  644.     mov    ax, offset ega_interrupt
  645.  
  646.     cli
  647.     xchg    es:[bx], ax
  648.     xchg    es:[bx+2], dx
  649.     mov    old_vector, ax
  650.     mov    old_vector+2, dx
  651.  
  652.     in    al, 21h            ; Get present mask
  653.     mov    old_irq_mask, al
  654.     and    al, 11111011b
  655.     out    21h, al
  656.  
  657.     mov    dx, ega_base_port
  658.     mov    ax, default_retrace
  659.     and    ah, 11001111b
  660.     out    dx, ax
  661.     jmp    short $+2
  662.     or    ah, 00010000b
  663.     out    dx, ax
  664.     sti
  665.  
  666. done:    ret
  667. ega_install endp
  668.  
  669.  
  670. ; EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  671. ;
  672. ; void EGA_RIP_OUT()
  673. ; Undoes all the interrupt processing for the EGA
  674. ; Given:
  675. ;    nothing
  676. ; Returns:
  677. ;    EGA interrupt vector removed
  678. public    ega_rip_out
  679. ega_rip_out proc uses es
  680.     mov    ax, old_vector        ; See if installed
  681.     or    ax, old_vector+2
  682.     jz    done            ; Return if not installed
  683.  
  684.     xor    ax, ax            ; ES -> base page
  685.     mov    es, ax
  686.     mov    bx, 0ah*4        ; Vector for IRQ 2
  687.     mov    ax, old_vector
  688.     mov    dx, old_vector+2
  689.     mov    old_vector, 0
  690.     mov    old_vector+2, 0
  691.     cli
  692.     mov    es:[bx], ax
  693.     mov    es:[bx+2], dx
  694.  
  695.     in    al, 21h
  696.     mov    ah, old_irq_mask    ; Restore old interrupt mask
  697.     and    ah, 1 shl 2
  698.     and    al, 11111011b
  699.     or    al, ah
  700.     out    21h, al
  701.  
  702.     mov    dx, 3d4h
  703.     mov    ax, 2b11h
  704.     out    dx, ax
  705.     sti
  706. done:    ret
  707. ega_rip_out endp
  708.  
  709.  
  710. ; EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
  711. ;
  712. ; void EGA_INTERRUPT( void )
  713. ; Handles all the interrupt processing for the EGA controller
  714. ; Given:
  715. ;    This is run at every IRQ-2 spike (ie. vertical retrace)
  716. ; Returns:
  717. ;    If FLIP_TURN is brought to zero, EGA visual pages are swapped
  718. ;    If swap is made, DO_PAGE_FLIP set to 0, DONE_PAGE_FLIP set to -1
  719.  
  720. ega_interrupt proc far
  721.     push    ax
  722.     push    dx
  723.     push    ds
  724.  
  725.     mov    ax, @DATA
  726.     mov    ds, ax
  727.  
  728.     mov    dx, 3c2h        ; DX -> I/O port for input status
  729.     in    al, dx
  730.     test    al, 1 shl 7
  731.     jnz    @F            ; Interrupt is ours
  732.     pushf
  733.     call    dword ptr [old_vector]
  734.     jmp    done
  735.  
  736. @@:    mov    dx, ega_base_port    ; DX -> EGA/VGA register port
  737.     in    al, dx
  738.     push    ax
  739.  
  740.     mov    ax, default_retrace
  741.     and    ah, 11101111b
  742.     out    dx, ax
  743.     jmp    short $+2
  744.  
  745.     mov    al, EOI
  746.     out    EOI_PORT, al
  747.     jmp    short $+2
  748.     sti
  749.  
  750.     dec    flip_turn
  751.     jnz    @F
  752.     mov    flip_turn, 4
  753.     cmp    do_page_flip, 0        ; See if we need to do this
  754.     jz    @F
  755.  
  756.     mov    al, 0ch            ; Select register for page MSB
  757.     mov    ah, byte ptr ega_segment+1
  758.     shl    ah, 4
  759.     out    dx, ax            ; Output the most significant byte
  760.     xor    ega_segment, 800h    ; Swap the active page
  761.     jmp    short $+2
  762.  
  763.     mov    do_page_flip, 0
  764.     mov    done_page_flip, -1
  765.  
  766. @@:    cli
  767.     mov    ax, default_retrace
  768.     and    ah, 11011111b
  769.     or    ah, 00010000b
  770.     out    dx, ax
  771.     jmp    short $+2
  772.     pop    ax
  773.     out    dx, al
  774.  
  775. done:    pop    ds
  776.     pop    dx
  777.     pop    ax
  778.  
  779.     iret
  780. ega_interrupt endp
  781.  
  782.  
  783.     end
  784.  
  785.  
  786.